{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 再说几句Python"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import pandas as pd"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 前情提要\n",
    "上两集中，我们学习了python的基本语法（数据类型、循环、字符串的处理、循环语句、判断语句、列表、怎么建立函数）和numpy的基本功能（array的概念、加减乘除、array的shape、如何得到array的元素、建立mask array等等）。请先回顾之前的内容。\n",
    "\n",
    "这次补充几个关于python语言的高级用法，为之后讲爬虫和pandas做一点铺垫。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### `map` and `lambda`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "仅在定义匿名函数的地方使用这个函数，其他地方用不到，所以就不需要给它取个阿猫阿狗之类的名字了。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0.21484375, 0.48828125, 0.1328125]"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[i / 256 for i in [55, 125, 34]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "def func(x):\n",
    "    return x + 5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "9"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "func(4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<map at 0x7fe6804a07b8>"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "map(func, [4, 5, 6, 7])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[9, 10, 11, 12]"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(map(func, [4, 5, 6, 7]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[9]"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(map(lambda x: x + 5, [4]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[9, 10, 11, 12]"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(map(lambda x: x + 5, [4, 5, 6, 7]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "provinceName = [\"湖北\", \"浙江\", \"江西\", \"安徽\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "def append_sheng(x):\n",
    "    return x + '省'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['湖北省', '浙江省', '江西省', '安徽省']"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(map(append_sheng, provinceName))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['湖北省', '浙江省', '江西省', '安徽省']"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "provinceFullName = list(map(lambda x: x + '省', provinceName))\n",
    "provinceFullName"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [],
   "source": [
    "provinceName = [\"湖北\", \"浙江\", \"江西省\", \"安徽\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['湖北省', '浙江省', '江西省省', '安徽省']"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "provinceFullName = list(map(lambda x: x + '省', provinceName))\n",
    "provinceFullName"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['湖北省', '浙江省', '江西省', '安徽省']"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "provinceFullName = list(map(lambda x: x.rstrip('省') + '省', provinceName))\n",
    "provinceFullName"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### `enumerate` and `zip`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [],
   "source": [
    "infection = [27100, 1075, 740, 779]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "for prov in provinceFullName:\n",
    "    if prov == '浙江省':\n",
    "        # 浙江有多少人感染？？？"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Infections = 1075\n"
     ]
    }
   ],
   "source": [
    "for i, prov in enumerate(provinceFullName):\n",
    "    if prov == '浙江省':\n",
    "        # 浙江有多少人感染？？？\n",
    "        print('Infections = {}'.format(infection[i]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "用两个数组 provinceFullName 和 infection 来表达疫情，没有很好的结构性，不好一一对应。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[('湖北省', 27100), ('浙江省', 1075), ('江西省', 740), ('安徽省', 779)]"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(zip(provinceFullName, infection))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "练习1: print \"{city} is in {state}\" for each combination."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [],
   "source": [
    "cities = [\"Phoenix\", \"Austin\", \"San Diego\", \"New York\"]\n",
    "states = [\"Arizona\", \"Texas\", \"California\", \"New York\"]\n",
    "\n",
    "couple = list(zip(cities, states))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 ('Phoenix', 'Arizona')\n",
      "1 ('Austin', 'Texas')\n",
      "2 ('San Diego', 'California')\n",
      "3 ('New York', 'New York')\n"
     ]
    }
   ],
   "source": [
    "for i, city in enumerate(couple):\n",
    "    print(i, city)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[('Phoenix', 'Arizona'),\n",
       " ('Austin', 'Texas'),\n",
       " ('San Diego', 'California'),\n",
       " ('New York', 'New York')]"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "couple"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['Phoenix is in Arizona',\n",
       " 'Austin is in Texas',\n",
       " 'San Diego is in California',\n",
       " 'New York is in New York']"
      ]
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "['{0} is in {1}'.format(item[0], item[1]) for item in couple]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "练习2: 湖北每日新增多少确诊病例？"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [],
   "source": [
    "hubei_infection = [270,   444,   444,   729,   761,  1423,  1423,  3554,  4586, \n",
    "                   5806,  5806,  9074,  9074, 13522, 16678, 19665, 22112, 24953, \n",
    "                   27100, 27100] # from Jan 21"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "20"
      ]
     },
     "execution_count": 50,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(hubei_infection)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[174,\n",
       " 0,\n",
       " 285,\n",
       " 32,\n",
       " 662,\n",
       " 0,\n",
       " 2131,\n",
       " 1032,\n",
       " 1220,\n",
       " 0,\n",
       " 3268,\n",
       " 0,\n",
       " 4448,\n",
       " 3156,\n",
       " 2987,\n",
       " 2447,\n",
       " 2841,\n",
       " 2147,\n",
       " 0]"
      ]
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[hubei_infection[i + 1] - num for i, num in enumerate(hubei_infection[:-1])]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 词典 `dict` and `set`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'湖北省': 27100, '浙江省': 1075, '江西省': 740, '安徽省': 779}"
      ]
     },
     "execution_count": 59,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "NCP_infection = dict(list(zip(provinceFullName, infection)))\n",
    "NCP_infection"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "27100"
      ]
     },
     "execution_count": 61,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "NCP_infection['湖北省']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "779"
      ]
     },
     "execution_count": 62,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "NCP_infection['安徽省']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {},
   "outputs": [
    {
     "ename": "KeyError",
     "evalue": "'四川省'",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mKeyError\u001b[0m                                  Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-63-939bcd6a48c3>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mNCP_infection\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'四川省'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;31mKeyError\u001b[0m: '四川省'"
     ]
    }
   ],
   "source": [
    "NCP_infection['四川省']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "dict_keys(['湖北省', '浙江省', '江西省', '安徽省'])"
      ]
     },
     "execution_count": 64,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "NCP_infection.keys()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'湖北省': 27100, '浙江省': 1075, '江西省': 740, '安徽省': 779, '北京市': 326}"
      ]
     },
     "execution_count": 65,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "NCP_infection['北京市'] = 326\n",
    "NCP_infection"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[27100, 1075, 740, 779, 326]"
      ]
     },
     "execution_count": 77,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(NCP_infection.values())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['湖北省', '浙江省', '江西省', '安徽省', '北京市']"
      ]
     },
     "execution_count": 78,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(NCP_infection.keys())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "metadata": {},
   "outputs": [],
   "source": [
    "province_name = ['湖北省', '浙江省', '江西省', '安徽省', '北京市', '北京市', '安徽省']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 80,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'北京市', '安徽省', '江西省', '浙江省', '湖北省'}"
      ]
     },
     "execution_count": 80,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "set(province_name)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['江西省', '湖北省', '浙江省', '安徽省', '北京市']"
      ]
     },
     "execution_count": 81,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(set(province_name))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array(['北京市', '安徽省', '江西省', '浙江省', '湖北省'], dtype='<U3'),\n",
       " array([4, 3, 2, 1, 0]),\n",
       " array([2, 2, 1, 1, 1]))"
      ]
     },
     "execution_count": 85,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.unique(np.array(province_name), return_counts=True, return_index=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### `datetime` 每时每刻"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "datetime.datetime(2020, 2, 21, 18, 20, 34, 154692)"
      ]
     },
     "execution_count": 86,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import datetime\n",
    "now = datetime.datetime.now()\n",
    "now"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 87,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "datetime.datetime(2020, 2, 21, 18, 20)"
      ]
     },
     "execution_count": 87,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "now = now.replace(second=0, microsecond=0)\n",
    "now"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 88,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Timestamp('2020-02-21 18:20:00')"
      ]
     },
     "execution_count": 88,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pd.to_datetime(now)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "怎么把 '2019年10月11日 23:52' 转化机器能看懂的东西？"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 89,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "datetime.datetime(2019, 10, 11, 23, 52)"
      ]
     },
     "execution_count": 89,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "crush_time_str = '2019年10月11日 23:52'\n",
    "crush_time = datetime.datetime.strptime(crush_time_str, '%Y年%m月%d日 %H:%M')\n",
    "crush_time"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 90,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Timestamp('2019-10-11 23:52:00')"
      ]
     },
     "execution_count": 90,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pd.to_datetime(crush_time)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 91,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Timestamp('2019-10-12 23:52:00')"
      ]
     },
     "execution_count": 91,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pd.to_datetime(crush_time + datetime.timedelta(days=1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 92,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Timestamp('2020-10-10 23:52:00')"
      ]
     },
     "execution_count": 92,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pd.to_datetime(crush_time + datetime.timedelta(days=365))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 给函数写好注释，做一个负责任的女人\n",
    "行号"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 93,
   "metadata": {},
   "outputs": [],
   "source": [
    "def parse_time(time_str, fmt='%Y年%m月%d日 %H:%M', verbose=True): # why not using `format`?\n",
    "    '''\n",
    "    Parse the time given as a string.\n",
    "    \n",
    "    Parameters:\n",
    "        time_str (str): the input string, following the given format.\n",
    "        fmt (str): the format of input string. Default is '%Y年%m月%d日 %H:%M'.\n",
    "        verbose (bool): whether print out the parsed time.\n",
    "        \n",
    "    Return:\n",
    "        time (pd.Timestamp): parsed time.\n",
    "    '''\n",
    "    import pandas as pd\n",
    "    import datetime\n",
    "    \n",
    "    time = pd.to_datetime(datetime.datetime.strptime(time_str, fmt))\n",
    "    \n",
    "    if verbose:\n",
    "        print('The time is {}'.format(time))\n",
    "        \n",
    "    return time"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 97,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The time is 2019-10-11 23:52:00\n"
     ]
    }
   ],
   "source": [
    "crush_time = parse_time(crush_time_str, verbose=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 98,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Timestamp('2019-10-11 23:52:00')"
      ]
     },
     "execution_count": 98,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "crush_time"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### * 和 **"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "def parse_time(time_str, fmt='%Y年%m月%d日 %H:%M', verbose=True, **kwds): # why not using `format`?\n",
    "    '''\n",
    "    Parse the time given as a string.\n",
    "    \n",
    "    Parameters:\n",
    "        time_str (str): the input string, following the given format.\n",
    "        fmt (str): the format of input string. Default is '%Y年%m月%d日 %H:%M'.\n",
    "        verbose (bool): whether print out the parsed time.\n",
    "        \n",
    "    Return:\n",
    "        time (pd.Timestamp): parsed time.\n",
    "    '''\n",
    "    import pandas as pd\n",
    "    import datetime\n",
    "    \n",
    "    time = pd.to_datetime(datetime.datetime.strptime(time_str, fmt))\n",
    "    \n",
    "    if 'is_why' in kwds.keys():\n",
    "        print('WHY is comming!!!!!!!')\n",
    "    \n",
    "    if verbose:\n",
    "        if 'time_name' in kwds.keys():\n",
    "            print('{0} is {1}'.format(kwds['time_name'], time))\n",
    "        else:\n",
    "            print('Time is {0}'.format(time))\n",
    "    \n",
    "    return time"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "why is 2019-10-11 23:52:00\n"
     ]
    }
   ],
   "source": [
    "crush_time_str = '2019年10月11日 23:52'\n",
    "crush_time = parse_time(crush_time_str, verbose=True, time_name='why')\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "def parse_time(time_str, fmt='%Y年%m月%d日 %H:%M', verbose=True, *args): # why not using `format`?\n",
    "    '''\n",
    "    Parse the time given as a string.\n",
    "    \n",
    "    Parameters:\n",
    "        time_str (str): the input string, following the given format.\n",
    "        fmt (str): the format of input string. Default is '%Y年%m月%d日 %H:%M'.\n",
    "        verbose (bool): whether print out the parsed time.\n",
    "        \n",
    "    Return:\n",
    "        time (pd.Timestamp): parsed time.\n",
    "    '''\n",
    "    import pandas as pd\n",
    "    import datetime\n",
    "    \n",
    "    time = pd.to_datetime(datetime.datetime.strptime(time_str, fmt))\n",
    "    \n",
    "    if verbose:\n",
    "        print('{0} is {1}'.format(args, time))\n",
    "    \n",
    "    return time"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "('Hahaha',) is 2019-10-11 23:52:00\n"
     ]
    }
   ],
   "source": [
    "crush_time_str = '2019年10月11日 23:52'\n",
    "crush_time = parse_time(crush_time_str, '%Y年%m月%d日 %H:%M', True, 'Hahaha')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [],
   "source": [
    "def multi_sum(*args):\n",
    "    print(args)\n",
    "    s = 0\n",
    "    for item in args:\n",
    "        s += item\n",
    "    return s"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(1, 2, 3, 4, 5)\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "15"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "multi_sum(1, 2, 3, 4, 5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### assert"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {
    "code_folding": []
   },
   "outputs": [],
   "source": [
    "def parse_time(time_str, fmt='%Y年%m月%d日 %H:%M', verbose=True): # why not using `format`?\n",
    "    '''\n",
    "    Parse the time given as a string.\n",
    "    \n",
    "    Parameters:\n",
    "        time_str (str): the input string, following the given format.\n",
    "        fmt (str): the format of input string. Default is '%Y年%m月%d日 %H:%M'.\n",
    "        verbose (bool): whether print out the parsed time.\n",
    "        \n",
    "    Return:\n",
    "        time (pd.Timestamp): parsed time.\n",
    "    '''\n",
    "    import pandas as pd\n",
    "    import datetime\n",
    "    assert(isinstance(time_str, str)), '你的数据类型错了！🐧'\n",
    "    time = pd.to_datetime(datetime.datetime.strptime(time_str, fmt))\n",
    "    \n",
    "    if verbose:\n",
    "        print('The time is {}'.format(time))\n",
    "        \n",
    "    return time"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "ename": "AssertionError",
     "evalue": "你的数据类型错了！🐧",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mAssertionError\u001b[0m                            Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-43-6601d8b4b18f>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0mcrush_time_str\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m2019\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mcrush_time\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mparse_time\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcrush_time_str\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;32m<ipython-input-42-093e0a23074f>\u001b[0m in \u001b[0;36mparse_time\u001b[0;34m(time_str, fmt, verbose)\u001b[0m\n\u001b[1;32m     13\u001b[0m     \u001b[0;32mimport\u001b[0m \u001b[0mpandas\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mpd\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     14\u001b[0m     \u001b[0;32mimport\u001b[0m \u001b[0mdatetime\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 15\u001b[0;31m     \u001b[0;32massert\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtime_str\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mstr\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'你的数据类型错了！🐧'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     16\u001b[0m     \u001b[0mtime\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mpd\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mto_datetime\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdatetime\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdatetime\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstrptime\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtime_str\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfmt\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     17\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mAssertionError\u001b[0m: 你的数据类型错了！🐧"
     ]
    }
   ],
   "source": [
    "crush_time_str = 2019\n",
    "crush_time = parse_time(crush_time_str)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 面向对象编程\n",
    "对象：http://astrojacobli.github.io\n",
    "🐘🐘\n",
    "\n",
    "以前写程序的办法都是流程式编程，现在要搞对象（object）。\n",
    "\n",
    "对象：attributes + methods"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "class -> object"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 89,
   "metadata": {},
   "outputs": [],
   "source": [
    "class People:\n",
    "    def __init__(self, name, gender, alias, ):\n",
    "        self.name = name\n",
    "        self.gender = gender\n",
    "        self.alias = alias\n",
    "        self.hunger = 0\n",
    "        self.thirsty = 0\n",
    "        self.health = 100\n",
    "        self.love = 10\n",
    "        \n",
    "    def eat(self, amount=1):\n",
    "        if self.hunger - amount >= 0:\n",
    "            self.hunger -= amount\n",
    "    \n",
    "    def drink(self, amount=1):\n",
    "        if self.thirsty - amount >= 0:\n",
    "            self.thirsty -= amount\n",
    "    \n",
    "    def exercise(self, time=1):\n",
    "        if time > 5:\n",
    "            self.health -= 5 * time\n",
    "        else:\n",
    "            self.health += 10 * time\n",
    "        \n",
    "    def meowmeow(self):\n",
    "        self.love += 1\n",
    "        \n",
    "    def video_call(self):\n",
    "        self.love += 10\n",
    "    \n",
    "    def quarrel(self, others):\n",
    "        assert(isinstance(others, People)), '你不是人！！！'\n",
    "        self.love -= 10\n",
    "        self.health -= 20\n",
    "        self.thirsty += 10\n",
    "        \n",
    "        others.love -= 5\n",
    "        others.health -= 10\n",
    "        others.thirsty += 5\n",
    "    \n",
    "    def check_healthy(self):\n",
    "        if self.thirsty > 30 or self.hunger > 30:\n",
    "            self.health -= 30\n",
    "        if self.health < 50:\n",
    "            return 'unhealthy'\n",
    "        else:\n",
    "            return 'healthy'\n",
    "    \n",
    "    def write_diary(self, stuff=None):\n",
    "        ## Basic status\n",
    "        healthy = self.check_healthy()\n",
    "        diary = \"I'm {}\".format(healthy) + ' today'\n",
    "        diary = \"\\n\".join([diary, stuff])\n",
    "        self.diary = diary\n",
    "        \n",
    "    def make_love(self, others):\n",
    "        assert(isinstance(others, People)), '你不是人！！！'\n",
    "        self.love += 100\n",
    "        others.love += 100"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 91,
   "metadata": {},
   "outputs": [],
   "source": [
    "babyxuan = People(name='LJX', gender='Male', alias='XX')\n",
    "babyhuan = People(name='WHY', gender='Female', alias='Huanhuan')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 104,
   "metadata": {},
   "outputs": [],
   "source": [
    "params = 'WHY', 'Female', 'Huanhuan'\n",
    "babyhuan = People(*params)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 106,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'name': 'WHY',\n",
       " 'gender': 'Female',\n",
       " 'alias': 'Huanhuan',\n",
       " 'hunger': 0,\n",
       " 'thirsty': 0,\n",
       " 'health': 100,\n",
       " 'love': 10}"
      ]
     },
     "execution_count": 106,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "babyhuan.__dict__"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 92,
   "metadata": {},
   "outputs": [],
   "source": [
    "babyhuan.make_love(babyxuan)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 94,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'name': 'LJX',\n",
       " 'gender': 'Male',\n",
       " 'alias': 'XX',\n",
       " 'hunger': 0,\n",
       " 'thirsty': 10,\n",
       " 'health': 80,\n",
       " 'love': 100}"
      ]
     },
     "execution_count": 94,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "babyxuan.__dict__"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 100,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'name': 'WHY',\n",
       " 'gender': 'Female',\n",
       " 'alias': 'Huanhuan',\n",
       " 'hunger': 0,\n",
       " 'thirsty': 5,\n",
       " 'health': 90,\n",
       " 'love': 105}"
      ]
     },
     "execution_count": 100,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "babyhuan.__dict__"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 98,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'healthy'"
      ]
     },
     "execution_count": 98,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "babyhuan.eat(10)\n",
    "babyhuan.drink(30)\n",
    "babyhuan.check_healthy()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [],
   "source": [
    "babyhuan.write_diary(\"I don't read some papers today. \")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "I'm healthy today\n",
      "I don't read some papers today. \n"
     ]
    }
   ],
   "source": [
    "print(babyhuan.diary)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [],
   "source": [
    "babyhuan.video_call()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "20"
      ]
     },
     "execution_count": 58,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "babyhuan.love"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'name': 'WHY',\n",
       " 'gender': 'Female',\n",
       " 'alias': 'Huanhuan',\n",
       " 'hunger': 0,\n",
       " 'thirsty': 55,\n",
       " 'health': -40,\n",
       " 'love': -35,\n",
       " 'diary': \"I'm unhealthy today\\nF**K! I quarreled a lot today! \"}"
      ]
     },
     "execution_count": 68,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "babyhuan.__dict__"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 103,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[\"I'm\", 'unhealthy', 'today']"
      ]
     },
     "execution_count": 103,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\"I'm unhealthy today\".split(' ')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "其实python里一切东西都是对象。比如字符串有method叫做split."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
